package com.loong.framework.handler;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;

import java.util.List;

import com.loong.framework.properties.TenantProperties;
import com.loong.framework.utils.CommonUtil;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;

/**
 * 多租户处理器实现TenantLineHandler接口
 *
 * @author hege @Date 2023-08-25
 */
public class MultiTenantHandler implements TenantLineHandler {

  private final TenantProperties properties;

  public MultiTenantHandler(TenantProperties properties) {
    this.properties = properties;
  }

  /**
   * 获取租户ID值表达式，只支持单个ID值 (实际应该从用户信息中获取)
   *
   * @return 租户ID值表达式
   */
  @Override
  public Expression getTenantId() {

    Object loginId = StpUtil.getLoginId();
    // 实际应该从用户信息中获取
    if (CommonUtil.notNullOrEmpty(loginId)) {
      Object tenantId = StpUtil.getSession().get("tenantId");
      if (CommonUtil.notNullOrEmpty(tenantId)) {
        return new StringValue(String.valueOf(tenantId));
      }
    }

    return new StringValue("");
  }

  /**
   * 获取租户字段名,默认字段名叫: tenant_id
   *
   * @return 租户字段名
   */
  @Override
  public String getTenantIdColumn() {
    return properties.getColumn();
  }

  /**
   * 根据表名判断是否忽略拼接多租户条件
   *
   * <p>默认都要进行解析并拼接多租户条件
   *
   * @param tableName 表名
   * @return 是否忽略, true:表示忽略，false:需要解析并拼接多租户条件
   */
  @Override
  public boolean ignoreTable(String tableName) {
    try {
      boolean login = StpUtil.isLogin();

      if (!login) {
        return true;
      }
      SaSession session = StpUtil.getSession();
      // 忽略指定用户对租户的数据过滤
      List<String> ignoreLoginNames = properties.getIgnoreLoginNames();
      Object loginName = session.get("loginName");
      if (null != ignoreLoginNames && ignoreLoginNames.contains((String) loginName)) {
        return true;
      }

      // 忽略指定表对租户数据的过滤
      List<String> ignoreTables = properties.getIgnoreTables();
      return null != ignoreTables && ignoreTables.contains(tableName);
    } catch (Exception e) {
      return true;
    }
  }
}
